package com.gzsxy.esjy.service.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gzsxy.esjy.common.base.exception.impl.BusinessException;
import com.gzsxy.esjy.common.base.exception.impl.CustomAssert;
import com.gzsxy.esjy.common.base.result.ResultCodeEnum;
import com.gzsxy.esjy.service.base.dto.request.CategoryRequest;
import com.gzsxy.esjy.service.base.dto.response.PageResult;
import com.gzsxy.esjy.service.base.util.TreeUtil;
import com.gzsxy.esjy.service.base.dto.response.CategoryRsp;
import com.gzsxy.esjy.service.base.util.ValidateUtil;
import com.gzsxy.esjy.service.base.DictionaryConstants;
import com.gzsxy.esjy.service.product.dao.CategoryMapper;
import com.gzsxy.esjy.service.product.entity.Category;
import com.gzsxy.esjy.service.product.entity.vo.CategoryQueryVo;
import com.gzsxy.esjy.service.product.service.CategoryService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 类型 服务实现类
 * </p>
 *
 * @author zxl
 * @since 2021-11-02
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {


    @Autowired
    private CategoryMapper categoryMapper;




    /**
     * 1. 查询redis缓存中是否存在需要的数据 haskey
     * 2. 如果缓存不存在从数据库中取出数据，并将数据存入缓存 set
     * 3. 如果缓存存在则从缓存中读取数据 get
     * @description: 分页查询商品分类
     *  @param pageParam 分页数据
     * @param categoryQueryVo 查询对象
     * @return
     */
    @Cacheable(value = "index", key = "'selectPage'")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public PageResult<CategoryRsp> selectPage(IPage<?> pageParam, CategoryQueryVo categoryQueryVo) {
        //显示分页查询列表
        // 1.排序：按照sort字段排序
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();//条件构造器

        queryWrapper.eq("is_deleted",0);

        String categoryName = categoryQueryVo.getCategoryName();
        String id = categoryQueryVo.getId();
        String categoryLevel = categoryQueryVo.getCategoryLevel();
        if (StringUtils.isEmpty(categoryName) && StringUtils.isEmpty(id)){
            queryWrapper.eq("category_level",0);
        }
        if(StringUtils.isNotEmpty(categoryName)) {
            queryWrapper.like("category_name",categoryName);
        }
        if (StringUtils.isNotEmpty(id)){
            queryWrapper.eq("id",id);
        }
        if (StringUtils.isNotEmpty(categoryLevel)){
            queryWrapper.eq("category_level",categoryLevel);
        }
        //分页查询
        //1.查询所有一级分类并分页查询
        List<CategoryRsp> records = null;
        IPage<CategoryRsp> rspIPage = null;
        if (pageParam !=null){
            rspIPage = baseMapper.selectPageByCateQueryVo(pageParam,queryWrapper);
            records = rspIPage.getRecords();
            //普通查询
        } else {
            List<Category> categories = baseMapper.selectList(queryWrapper);
            records = JSON.parseArray(JSON.toJSONString(categories), CategoryRsp.class);
        }

        //分层查询
        LambdaQueryWrapper<Category> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Category::getDeleted,DictionaryConstants.NUMBER_0);
        Integer type = categoryQueryVo.getType();
        if (type != null){
            switch (type) {
                //获取层数1
                case 1:
                    wrapper.in(Category::getCategoryLevel, 0);
                    break;
                case 2:
                    wrapper.in(Category::getCategoryLevel, 0, 1);
                    break;
                default:
                    wrapper.in(Category::getCategoryLevel, 0, 1, 2);
            }
        }

        //2.查询所有的分类树-未分页
        List<Category> categories = categoryMapper.selectList(wrapper);
        //实现list的拷贝
        List<CategoryRsp> list = JSON.parseArray(JSON.toJSONString(categories), CategoryRsp.class);
        //组装数据成树形
        List<CategoryRsp> build = TreeUtil.build(list,Comparator.comparing(CategoryRsp::getOrderId).reversed());

        //将分页查询的内容内插入所有的下级分类
        for (CategoryRsp record : records) {
            for (int i = 0; i < build.size(); i++) {
                if (record.getId().equals(build.get(i).getId())){
                    record.setChildren(build.get(i).getChildren());
                }
            }
        }
        //返回结果集
        PageResult<CategoryRsp> pageResult = new PageResult<CategoryRsp>();
        if (rspIPage != null){
            rspIPage.setRecords(records);
            //总记录数
            pageResult.setTotal(rspIPage.getTotal());
        }
        //获取查询的总结果
        pageResult.setRecords(records);
        return pageResult;
    }


    /**
     * @description: 添加商品分类
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addCategory(CategoryRequest categoryRequest) {
        //校验唯一菜单
        ValidateUtil.assertUnique(categoryMapper::existByCategoryName,categoryRequest.getCategoryName(), ResultCodeEnum.PRODUCT_CATEGORY_EXIST_ERROR.getMessage());

        Category category = new Category();
        BeanUtils.copyProperties(categoryRequest,category);
        baseMapper.insert(category);
    }


    /**
     * @description: 更新商品分类
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateCategory(CategoryRequest categoryRequest) {
        Category category = baseMapper.selectById(categoryRequest.getId());
        //商品分类不存在
        CustomAssert.notTrue(ObjectUtils.isNotEmpty(category),ResultCodeEnum.PRODUCT_CATEGORY_NOT_FOUND.getMessage(),ResultCodeEnum.PRODUCT_CATEGORY_NOT_FOUND.getCode());
        Category category1 = new Category();
        BeanUtils.copyProperties(categoryRequest,category1);
        //修改了商品分类名
        if (!category.getCategoryName().equals(categoryRequest.getCategoryName())){
            //校验唯一菜单
            ValidateUtil.assertUnique(categoryMapper::existByCategoryName,categoryRequest.getCategoryName(), ResultCodeEnum.PRODUCT_CATEGORY_EXIST_ERROR.getMessage());
        }
        baseMapper.updateById(category1);
    }


    /**
     * @description: 删除分类
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteCategory(String categoryId, Boolean isConform) {
        Category category = baseMapper.selectById(categoryId);
        //商品分类不存在
        CustomAssert.notTrue(ObjectUtils.isNotEmpty(category),ResultCodeEnum.PRODUCT_CATEGORY_NOT_FOUND.getMessage(),ResultCodeEnum.PRODUCT_CATEGORY_NOT_FOUND.getCode());
        List<String> deleteList = new ArrayList<>();
        deleteList.add(categoryId);
        //存在子分类
        if (baseMapper.existChildren(categoryId)){
            if (!isConform){
                throw new BusinessException(ResultCodeEnum.CATEGORY_DELETE_FAILED_EXIST_CHILDREN.getMessage());
            }
            //获取子分类
            LambdaQueryWrapper<Category> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(Category::getParentId,categoryId);
            List<Category> list = baseMapper.selectList(wrapper);
            //获取子分类id集合
            List<String> idList = list.stream().map(Category::getId).collect(Collectors.toList());
            deleteList.addAll(idList);
        }
        baseMapper.deleteBatchIds(deleteList);
    }

    /**
     * @description: 前台根据 分类层级 0: 顶级 1:二级 2:三级 获取分类列表
     * @param
     * @return
     */
    @Override
    public List<CategoryRsp> getByLevel(Integer level) {
        LambdaQueryWrapper<Category> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Category::getCategoryLevel,level);
        List<Category> list = categoryMapper.selectList(wrapper);
        List<CategoryRsp> categoryList = JSON.parseArray(JSON.toJSONString(list), CategoryRsp.class);
        return categoryList;
    }
}
